﻿#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Net;
using BattleNET;
using System.Globalization;
using System.Diagnostics;
#endregion

namespace DayZAntiHax
{
    public class Process : IProcess
    {
        //Declarations
        #region
        static int s_iNumPasses = 1;
        
        List<String> m_BannableObjects;
        List<String> m_BannableVariables;
        List<String> m_BannableDamage;
        List<String[]> m_GuidsToBeBanned;
        List<String[]> m_IPsToBeBanned;
        List<String> m_BannedGuids;
        List<String> m_BannedIPs;
        int m_iNumGuidsBanned;
        String result;
        public bool m_bLastLineCR = false;

        private double m_dParsingFrequency = 60; //second between log file checks for enabled scans
        private double m_dMessageFrequency = 10; //multiplier - how many parses between messages
        private double m_dBanListFrequency = 10; //multiplier - how many parses between banloads
        private double m_dFilterFrequency = 10; //multiplier - how many parses between filter updates
        private bool m_bShouldShowMessage = true;  //Stop the spam
        private bool m_bShouldCheckForFlooding = true;
        private bool m_bShouldUseCBL = true;
        private bool m_bShouldBanIP = false;
        BattlEyeLoginCredentials m_BECredentials;

        public IBattleNET b;
        
        private string[,] m_sFilterURL = new string[,] { { "http://dayz-community-banlist.googlecode.com/git/filters/scripts.txt", "scripts" },
                                                        {"http://dayz-community-banlist.googlecode.com/git/filters/publicvariable.txt", "publicvariable" },
                                                        {"http://dayz-community-banlist.googlecode.com/git/filters/setdamage.txt", "setdamage" },
                                                        {"http://dayz-community-banlist.googlecode.com/git/filters/createvehicle.txt", "createvehicle" },
                                                        {"http://dayz-community-banlist.googlecode.com/git/filters/publicvariableval.txt", "publicvariableval" },
                                                        {"http://dayz-community-banlist.googlecode.com/git/filters/setpos.txt", "setpos" },
                                                        {"http://dayz-community-banlist.googlecode.com/git/filters/remoteexec.txt", "remoteexec" },
                                                        {"http://dayz-community-banlist.googlecode.com/git/filters/mpeventhandler.txt", "mpeventhandler" }
                                                      };
        
        private bool[] m_bFilterUpdate = new bool[] { true,     //Scripts
                                                      true,     //PublicVariable
                                                      true,     //SetDamage
                                                      true,     //CreateVehicle
                                                      true,     //PublicVariableVal
                                                      true,     //SetPos
                                                      true,     //RemoteExec
                                                      true      //MPEventHandler
                                                    };
        
        private bool[] m_bFilterScan = new bool[]   { true,     //0 Scripts
                                                      true,     //1 PublicVariable
                                                      true,     //2 SetDamage
                                                      true,     //3 CreateVehicle
                                                      true,     //4 PublicVariable
                                                      true,     //5 SetPos
                                                      true,     //6 RemoteExec
                                                      true      //7 MPEventHandler
                                                    };
        #endregion

        //EventHandlers
        #region
        public void Disconnected(BattlEyeDisconnectEventArgs args)
        {
            //Console.WriteLine(args.Message);
        }

        public void DumpMessage(BattlEyeMessageEventArgs args)
        {
            //Console.WriteLine(args.Message);
        }

        public BattlEyeLoginCredentials BECredentials
        {
            get
            {
                return m_BECredentials;
            }
        }

        public bool ShouldCheckForFlooding
        {
            get
            {
                return m_bShouldCheckForFlooding;
            }
        }

        public double ParsingFrequency
        {
            get
            {
                return m_dParsingFrequency;
            }
        }

        public Process()
        {
            
        }
        #endregion

        public bool Initialize()
        {
            {
                Console.ForegroundColor = ConsoleColor.DarkBlue;
                Console.BackgroundColor = ConsoleColor.DarkYellow;
                Console.WriteLine("                                        ");
                Console.WriteLine(" DayZ Anti-Hax                          ");
                Console.WriteLine(" Created by James 'GreyEcho' Pizzurro   ");
                Console.WriteLine(" Updated by Jeff 'Muppet1856' Zellen    ");
                Console.WriteLine("        and Kane 'k4n30' Goldsmith      ");
                Console.WriteLine("                                        ");
                Console.BackgroundColor = ConsoleColor.Black;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("========================================");
                Console.WriteLine("This software makes use of the BattleNET");
                Console.WriteLine("Library, under the LGPL and distributed");
                Console.WriteLine("under said license.");
                Console.WriteLine("Credit to:");
                Console.WriteLine("Vipeax & ziellos2k");
                Console.WriteLine("https://github.com/ziellos2k/BattleNET");
                Console.WriteLine("========================================");
                Console.ForegroundColor = ConsoleColor.Gray;
                // Get our list of bannable objects (defined by the user)
                m_BannableObjects = new List<String>();
                try
                {
                    FileInfo file = new FileInfo("objects.lst");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        m_BannableObjects.Add(line);
                    }
                    reader.Close();
                }
                catch (Exception)
                {
                    Console.WriteLine("     ERROR: Failed to read from objects.lst!");
                    Console.WriteLine("            Make sure it is located in the same directory as the executable!");
                    return false;
                }

                m_BannableVariables = new List<String>();
                try
                {
                    FileInfo file = new FileInfo("variables.lst");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        m_BannableVariables.Add(line);
                    }
                    reader.Close();
                }
                catch (Exception)
                {
                    Console.WriteLine("     ERROR: Failed to read from variables.lst!");
                    Console.WriteLine("            Make sure it is located in the same directory as the executable!");
                    return false;
                }

                m_BannableDamage = new List<String>();
                try
                {
                    FileInfo file = new FileInfo("damage.lst");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        m_BannableDamage.Add(line);
                    }
                    reader.Close();
                }
                catch (Exception)
                {
                    Console.WriteLine("     ERROR: Failed to read from damage.lst!");
                    Console.WriteLine("            Make sure it is located in the same directory as the executable!");
                    return false;
                }

                m_GuidsToBeBanned = new List<String[]>();
                m_BannedGuids = new List<String>();
                m_iNumGuidsBanned = 0;

                // Get configuration option values (defined by the user)
                #region
                try
                {
                    FileInfo file = new FileInfo("config.cfg");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        if (line.Contains("parsingFrequency"))
                        {
                            m_dParsingFrequency = Double.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("messageFrequency"))
                        {
                            m_dMessageFrequency = Double.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("banlistFrequency"))
                        {
                            m_dBanListFrequency = Double.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("filterFrequency"))
                        {
                            m_dFilterFrequency = Double.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("shouldCheckForFlooding"))
                        {
                            m_bShouldCheckForFlooding = Boolean.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("shouldShowMessage"))
                        {
                            m_bShouldShowMessage = Boolean.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("shouldUseCBL"))
                        {
                            m_bShouldUseCBL = Boolean.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("shouldBanIP"))
                        {
                            m_bShouldBanIP = Boolean.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains("serveraddress"))
                        {
                            m_BECredentials.Host = line.Split('=')[1];
                        }
                        else if (line.Contains("serverport"))
                        {
                            m_BECredentials.Port = Convert.ToInt32(line.Split('=')[1]);
                        }
                        else if (line.Contains("serverpassword"))
                        {
                            m_BECredentials.Password = line.Split('=')[1];
                        }
                        int i;
                        for (i = 0; i < m_sFilterURL.GetLength(0); i++)
                        {
                        if (line.Contains(m_sFilterURL[i,1]+"URL"))
                        {
                            m_sFilterURL[i,0] = line.Split('=')[1];
                        }
                        else if (line.Contains(m_sFilterURL[i, 1] + "Update"))
                        {
                            m_bFilterUpdate[i] = Boolean.Parse(line.Split('=')[1]);
                        }
                        else if (line.Contains(m_sFilterURL[i, 1] + "Scan"))
                        {
                            m_bFilterScan[i] = Boolean.Parse(line.Split('=')[1]);
                        }
                        }
                    }
                    reader.Close();
                }
                catch (Exception)
                {
                    Console.WriteLine("     ERROR: Failed to read from config.cfg!");
                    Console.WriteLine("            Make sure it is located in the same directory as the executable!");
                    return false;
                }
                #endregion

                return true;
            }

        }

        public void UpdateFiles()
        {
            try
            {
                using (var client = new WebClient())
                {
                    if (s_iNumPasses % m_dFilterFrequency == 0)
                    {
                        Console.Write("Downloading filters");
                        for (int i = 0; i < m_sFilterURL.GetLength(0); i++)
                        {
                            if (m_bFilterUpdate[i])
                            {
                                Console.Write("... " + m_sFilterURL[i, 1]);
                                client.DownloadFile(m_sFilterURL[i, 0], m_sFilterURL[i, 1] + ".txt");
                            }
                        }
                        Console.Write("\n");
                    }
                }
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to update local filters!");
            }
        }
        
        public void FindGuidsToBan()
        {
            // Check DayZ community ban list
            #region
            try
            {
                using (var client = new WebClient())
                {
                    if (s_iNumPasses % m_dBanListFrequency == 0 && m_bShouldUseCBL)
                    {
                        result = client.DownloadString("http://dayz-community-banlist.googlecode.com/git/bans/bans.txt").Replace('\n', ' ');
                        String[] items = result.Split(' ');
                        foreach (String item in items)
                        {
                            try
                            {
                                Guid.Parse(item);
                            }
                            catch (Exception)
                            {
                                continue;
                            }

                            if (m_GuidsToBeBanned.Contains(new String[5] { item, "DayZ Community Banlist", String.Empty, String.Empty, String.Empty }))
                                continue;

                            m_GuidsToBeBanned.Add(new String[5] { item, "DayZ Community Banlist", String.Empty, String.Empty, String.Empty });
                        }
                    }
                }
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to retrieve DayZ community ban list!");
            }
            #endregion

            // Check publicvariable.log
            #region
            try
            {
                if (m_bFilterScan[1])
                {
                    // First pass
                    /*FileInfo file = new FileInfo("publicvariable.log");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)*/
                    string[] lines = File.ReadAllLines("publicvariable.log");
                    foreach (string line in lines)
                    {
                        String[] items = line.Split(' ');

                        bool bannableVariableFound = false;
                        foreach (String item in m_BannableVariables)
                        {
                            if (items.Contains(item))
                            {
                                bannableVariableFound = true;
                                break;
                            }
                        }

                        if (bannableVariableFound)
                        {
                            for (int i = 0; i < items.Length; i++)
                            //foreach (String item in items)
                            {
                                try
                                {
                                    Guid.Parse(items[i]);
                                }
                                catch (Exception)
                                {
                                    continue;
                                }

                                if (m_GuidsToBeBanned.Contains(new String[5] { items[i], "Accessing Public Variable", items[0], items[1], "publicvariable.log" }))
                                    continue;

                                m_GuidsToBeBanned.Add(new String[5] { items[i], "Accessing Public Variable", items[0], items[1], "publicvariable.log" });
                                
                                if (m_bShouldBanIP)
                                {
                                    if (m_IPsToBeBanned.Contains(new String[5] { items[i-1].Substring(1,items[i-1].Length -2), "Accessing Public Variable", items[0], items[1], "publicvariable.log" }))
                                        continue;

                                    m_IPsToBeBanned.Add(new String[5] { items[i-1].Substring(1, items[i-1].Length - 2), "Accessing Public Variable", items[0], items[1], "publicvariable.log" });
                                }
                            }
                        }
                    }
                    //reader.Close();
                    lines = null;
                }
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to read from publicvariable.log!");
                Console.WriteLine("     The file may not exist as BE hasn't created it yet, you can ignore this message if");
                Console.WriteLine("     you make sure the executable is located in your server's '/BattlEye' directory!");
            }
            #endregion

            // Check setdamage.log
            #region
            try
            {
                if (m_bFilterScan[2])
                {
                    // First pass
                    /*FileInfo file = new FileInfo("setdamage.log");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)*/
                    string[] lines = File.ReadAllLines("setdamage.log");
                    foreach (string line in lines)
                    {
                        String[] items = line.Split(' ');

                        bool bannableDamageFound = false;
                        foreach (String item in m_BannableDamage)
                        {
                            if (items.Contains(item))
                            {
                                bannableDamageFound = true;
                                break;
                            }
                        }

                        if (bannableDamageFound)
                        {
                            for (int i = 0; i < items.Length; i++)
                            //foreach (String item in items)
                            {
                                try
                                {
                                    Guid.Parse(items[i]);
                                }
                                catch (Exception)
                                {
                                    continue;
                                }

                                if (m_GuidsToBeBanned.Contains(new String[5] { items[i], "Hacking Damage", items[0], items[1], "setdamage.log" }))
                                    continue;

                                m_GuidsToBeBanned.Add(new String[5] { items[i], "Hacking Damage", items[0], items[1], "setdamage.log" });

                                if (m_bShouldBanIP)
                                {
                                    if (m_IPsToBeBanned.Contains(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "Hacking Damage", items[0], items[1], "setdamage.log" }))
                                        continue;

                                    m_IPsToBeBanned.Add(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "Hacking Damage", items[0], items[1], "setdamage.log" });
                                }
                            }
                        }
                    }
                    //reader.Close();
                    lines = null;
                }
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to read from setdamage.log!");
                Console.WriteLine("     The file may not exist as BE hasn't created it yet, you can ignore this message if");
                Console.WriteLine("     you make sure the executable is located in your server's '/BattlEye' directory!");
            }
            #endregion

            // Check createvehicle.log
            #region
            try
            {
                if (m_bFilterScan[3])
                {
                    // First pass
                    /*FileInfo file = new FileInfo("createvehicle.log");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)*/
                    string[] lines = File.ReadAllLines("createvehicle.log");
                    foreach (string line in lines)
                    {
                        String[] items = line.Split(' ');

                        bool bannableObjectFound = false;
                        foreach (String item in m_BannableObjects)
                        {
                            if (items.Contains(item))
                            {
                                bannableObjectFound = true;
                                break;
                            }
                        }

                        if (bannableObjectFound)
                        {
                            for (int i = 0; i < items.Length; i++)
                            //foreach (String item in items)
                            {
                                try
                                {
                                    Guid.Parse(items[i]);
                                }
                                catch (Exception)
                                {
                                    continue;
                                }

                                if (m_GuidsToBeBanned.Contains(new String[5] { items[i], "Accessing Disallowed Object", items[0], items[1], "createvehicle.log" }))
                                    continue;

                                m_GuidsToBeBanned.Add(new String[5] { items[i], "Accessing Disallowed Object", items[0], items[1], "createvehicle.log" });

                                if (m_bShouldBanIP)
                                {
                                    if (m_IPsToBeBanned.Contains(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "Accessing Disallowed Object", items[0], items[1], "createvehicle.log" }))
                                        continue;

                                    m_IPsToBeBanned.Add(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "Accessing Disallowed Object", items[0], items[1], "createvehicle.log" });
                                }
                            }
                        }
                    }
                    //reader.Close();
                    
                    // Second pass
                    if (m_bShouldCheckForFlooding)
                    {
                        String[] lastDateTimeGUID = new String[3];
                        int iNumTimesLastDateTimeGUIDAppearsConsecutively = 1;
                        /*reader = file.OpenText();
                        while ((line = reader.ReadLine()) != null)*/
                        foreach (string line in lines)
                        {
                            String[] items = line.Split(' ');

                            int iGUIDIndex = -1;
                            String item;
                            for (int i = 0; i < items.Length; i++)
                            {
                                item = items[i];

                                try
                                {
                                    Guid.Parse(item);
                                }
                                catch (Exception)
                                {
                                    continue;
                                }

                                iGUIDIndex = i;
                                break;
                            }

                            if (iGUIDIndex == -1)
                                continue;

                            if (!items[0].Equals(lastDateTimeGUID[0]) || !items[1].Equals(lastDateTimeGUID[1]) || !items[iGUIDIndex].Equals(lastDateTimeGUID[2]))
                            {
                                lastDateTimeGUID[0] = items[0];
                                lastDateTimeGUID[1] = items[1];
                                lastDateTimeGUID[2] = items[iGUIDIndex];
                                iNumTimesLastDateTimeGUIDAppearsConsecutively = 1;
                                continue;
                            }

                            iNumTimesLastDateTimeGUIDAppearsConsecutively++;

                            if (iNumTimesLastDateTimeGUIDAppearsConsecutively >= 4)
                            {
                                if (m_GuidsToBeBanned.Contains(new String[5] { items[iGUIDIndex], "Object Access Flooding", items[0], items[1], "createvehicle.log" }))
                                    continue;

                                m_GuidsToBeBanned.Add(new String[5] { items[iGUIDIndex], "Object Access Flooding", items[0], items[1], "createvehicle.log" });

                                if (m_bShouldBanIP)
                                {
                                    if (m_IPsToBeBanned.Contains(new String[5] { items[iGUIDIndex - 1].Substring(1, items[iGUIDIndex - 1].Length - 2), "Object Access Flooding", items[0], items[1], "createvehicle.log" }))
                                        continue;

                                    m_IPsToBeBanned.Add(new String[5] { items[iGUIDIndex - 1].Substring(1, items[iGUIDIndex - 1].Length - 2), "Object Access Flooding", items[0], items[1], "createvehicle.log" });
                                }

                                lastDateTimeGUID[0] = String.Empty;
                                lastDateTimeGUID[1] = String.Empty;
                                lastDateTimeGUID[2] = String.Empty;
                                iNumTimesLastDateTimeGUIDAppearsConsecutively = 1;
                            }
                        }
                        //reader.Close();
                        lines = null;
                    }
                }
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to read from createvehicle.log!");
                Console.WriteLine("     The file may not exist as BE hasn't created it yet, you can ignore this message if");
                Console.WriteLine("     you make sure the executable is located in your server's '/BattlEye' directory!");
            }
            #endregion

            // Check remoteexec.log
            #region
            try
            {
                if (m_bFilterScan[6])
                {
                /*FileInfo file = new FileInfo("remoteexec.log");
                StreamReader reader = file.OpenText();
                String line;
                while ((line = reader.ReadLine()) != null)*/
                string[] lines = File.ReadAllLines("remoteexec.log");
                foreach (string line in lines)
                {
                    String[] items = line.Split(' ');
                    for (int i = 0; i < items.Length; i++)
                    //foreach (String item in items)
                    {
                        try
                        {
                            Guid.Parse(items[i]);
                        }
                        catch (Exception)
                        {
                            continue;
                        }

                        if (m_GuidsToBeBanned.Contains(new String[5] { items[i], "Remote Code Execution", items[0], items[1], "remoteexec.log" }))
                            continue;

                        m_GuidsToBeBanned.Add(new String[5] { items[i], "Remote Code Execution", items[0], items[1], "remoteexec.log" });

                        if (m_bShouldBanIP)
                        {
                            if (m_IPsToBeBanned.Contains(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "Remote Code Execution", items[0], items[1], "remoteexec.log" }))
                                continue;

                            m_IPsToBeBanned.Add(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "Remote Code Execution", items[0], items[1], "remoteexec.log" });
                        }
                    }
                }
                //reader.Close();
                lines = null;
            }}
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to read from remoteexec.log!");
                Console.WriteLine("     The file may not exist as BE hasn't created it yet, you can ignore this message if");
                Console.WriteLine("     you make sure the executable is located in your server's '/BattlEye' directory!");
            }
            #endregion

            // Check mpeventhandler.log
            #region
            try
            {
                if (m_bFilterScan[7])
                {
                    /*FileInfo file = new FileInfo("mpeventhandler.log");
                    StreamReader reader = file.OpenText();
                    String line;
                    while ((line = reader.ReadLine()) != null)*/
                    string[] lines = File.ReadAllLines("mpeventhandler.log");
                    foreach (string line in lines)
                    {
                        String[] items = line.Split(' ');
                        for (int i = 0; i < items.Length; i++)
                        //foreach (String item in items)
                        {
                            try
                            {
                                Guid.Parse(items[i]);
                            }
                            catch (Exception)
                            {
                                continue;
                            }

                            if (m_GuidsToBeBanned.Contains(new String[5] { items[i], "MP Event Handler Exception", items[0], items[1], "mpeventhandler.log" }))
                                continue;

                            m_GuidsToBeBanned.Add(new String[5] { items[i], "MP Event Handler Exception", items[0], items[1], "mpeventhandler.log" });

                            if (m_bShouldBanIP)
                            {
                                if (m_IPsToBeBanned.Contains(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "MP Event Handler Exception", items[0], items[1], "mpeventhandler.log" }))
                                    continue;

                                m_IPsToBeBanned.Add(new String[5] { items[i - 1].Substring(1, items[i - 1].Length - 2), "MP Event Handler Exception", items[0], items[1], "mpeventhandler.log" });
                            }
                        }
                    }
                    //reader.Close();
                    lines = null;
                }
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to read from mpeventhandler.log!");
                Console.WriteLine("     The file may not exist as BE hasn't created it yet, you can ignore this message if");
                Console.WriteLine("     you make sure the executable is located in your server's '/BattlEye' directory!");
            }
            #endregion

        }

        public void FindBannedGuids()
        {
            try
            {
                /*FileInfo file = new FileInfo("bans.txt");
                StreamReader reader = file.OpenText();
                String line;
                while ((line = reader.ReadLine()) != null)*/
                m_BannedGuids.Clear();
                m_BannedIPs.Clear();
                String[] lines = File.ReadAllLines("bans.txt");
                if (lines[lines.Length - 1] == "")
                {
                    m_bLastLineCR = true;
                }
                if (s_iNumPasses % m_dBanListFrequency == 0 && m_bShouldUseCBL)
                { 
                    lines = CleanupCBLBans(lines);
                }
                Guid ScrapGUID;
                IPAddress ScrapIP;
                foreach (String line in lines)
                {
                    String[] items = line.Split(' ');
                    if (Guid.TryParse(items[0],out ScrapGUID))
                    {
                        if (m_BannedGuids.Contains(items[0]))
                        {
                            continue;
                        }
                        m_BannedGuids.Add(items[0]);
                        continue;
                    }
                    if (m_bShouldBanIP && IPAddress.TryParse(items[0], out ScrapIP))
                    {
                        if (m_BannedIPs.Contains(items[0]))
                        {
                            continue; 
                        }
                        m_BannedIPs.Add(items[0]);
                    }
                }
                //reader.Close();
                lines = null;
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to read from bans.txt!");
                Console.WriteLine("     The file may not exist as BE hasn't created it yet, you can ignore this message if");
                Console.WriteLine("     you make sure the executable is located in your server's '/BattlEye' directory!");
            }
        }

        public void BanGuids()
        {
            try
            {
                foreach (String[] guid in m_GuidsToBeBanned)
                {
                    if (m_BannedGuids.Contains(guid[0]))
                        continue;   // guid has already been banned

                    using (StreamWriter writer = new StreamWriter("bans.txt", true))
                    {
                        if (!m_bLastLineCR)
                        {
                            writer.Write("/n");
                            m_bLastLineCR = true;
                        }
                        writer.WriteLine(guid[0] + " -1 DayZ Anti-Hax "+ DateTime.Now.ToString("g",CultureInfo.CreateSpecificCulture("de-DE")) + " (" + guid[1] + ")");
                        writer.Close();
                    }
                    using (StreamWriter writer = new StreamWriter("DayZAntiHax.log", true))
                    {
                        writer.WriteLine(DateTime.Now + " - Banned " + guid[0] + " on pass #" + s_iNumPasses + " for " + guid[1] + " (" + guid[2] + " " + guid[3] + " " + guid[4] + ")");
                        writer.Close();
                    }
                    m_BannedGuids.Add(guid[0]);
                    m_iNumGuidsBanned++;
                }

            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to write to bans.txt and/or DayZAntiHax.log!");
                Console.WriteLine("              Make sure the executable is located in your server's 'cfgdayz/BattlEye' directory!");
            }
        }

        public String[] CleanupCBLBans(String[] lines)
        {
            try
            {
                List<String> CBL = new List<String>();
                /*if (File.Exists("bans_DAH.old"))
                {
                    File.Delete("bans_DAH.old");
                }
                if (File.Exists("bans_DAH.tmp"))
                {
                    File.Delete("bans_DAH.tmp");
                }*/
                foreach (string line in lines)
                {
                    if (!line.Contains("DayZ Community Banlist"))
                    {
                        CBL.Add(line);
                    }
                }
                File.WriteAllLines("bans.txt", CBL);
                //File.Replace("bans_DAH.tmp", "bans.txt", "bans_DAH.old");
                /*if (File.Exists("bans_DAH.tmp"))
                {
                    File.Delete("bans_DAH.tmp");
                }*/
                //reader.Close();
                lines = null;
                lines = CBL.ToArray();
                CBL = null;
                return lines;
            }
            catch (Exception)
            {
                Console.WriteLine("     WARNING: Failed to read from bans.txt! Error in CBL Cleanup");
                Console.WriteLine("     The file may not exist as BE hasn't created it yet, you can ignore this message if");
                Console.WriteLine("     you make sure the executable is located in your server's '/BattlEye' directory!");
                return lines;
            }

        }

        public void Flush()
        {
            m_GuidsToBeBanned.Clear();
            m_iNumGuidsBanned = 0;
        }
        
        public void Execute(object state)
        {
            IBattleNET b = new BattlEyeClient(m_BECredentials);
            b.MessageReceivedEvent += DumpMessage;
            b.DisconnectEvent += Disconnected;
            b.ReconnectOnPacketLoss(true);

            // Check to see if should show message, if so check to see if pass number is reached to show it
            if (m_bShouldShowMessage && s_iNumPasses % m_dMessageFrequency == 0)
            {
                b.Connect();
                b.SendCommandPacket(EBattlEyeCommand.Say, "-1 This server protected by DayZ AntiHax");
                b.Disconnect();
            }
            
            Console.WriteLine(DateTime.Now + " - Starting pass #{0}...", s_iNumPasses);
            Console.WriteLine(DateTime.Now + " - Finding GUIDs to ban...");
            FindGuidsToBan(); // Check to see if any GUID's need banning
            if (m_GuidsToBeBanned.Count > 0 ) // If any bans are found in the logs or CBL
            {
                Console.WriteLine(DateTime.Now + " - Finding GUIDs already banned...");
                FindBannedGuids();
                Console.WriteLine(DateTime.Now + " - Banning GUIDs not already banned...");
                BanGuids();
                
                if (!(m_iNumGuidsBanned == 0))  //If there were ANY bans, load them into the server.
                {
                    b.Connect();
                    b.SendCommandPacket(EBattlEyeCommand.loadBans);
                    b.Disconnect();
                }
            }
            Console.WriteLine(DateTime.Now + " - {0} GUIDs banned. Cleaning up...", m_iNumGuidsBanned);
            Flush();
            Console.WriteLine(DateTime.Now + " - Pass #{0} complete.", s_iNumPasses);

            // Check for required filter updates
            if (s_iNumPasses % m_dFilterFrequency == 0)
            {
                bool UpdateFilters = false;
                for (int i = 1; i< m_bFilterUpdate.Length; i++)
                {
                    if (m_bFilterUpdate[i])
                    {
                        UpdateFilters = true;
                        break;
                    }
                }
                if (UpdateFilters || m_bFilterUpdate[0])
                {
                    UpdateFiles();
                    b.Connect();
                }
                if (m_bFilterUpdate[0]) //Check if scripts update is true
                {
                    b.SendCommandPacket(EBattlEyeCommand.loadScripts); //Load new scripts filter into server
                }
                
                if (UpdateFilters)
                {
                    b.SendCommandPacket(EBattlEyeCommand.loadEvents); //Load new filters into server
                }
                b.Disconnect();
            }
            s_iNumPasses++;
        }
    }
}
